﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using com.uplus.log4net;
using Microsoft.Exchange.WebServices.Autodiscover;
using Microsoft.Exchange.WebServices.Data;
using Newtonsoft.Json;
using WebApi.Bill.Biz;
using WebApi.Models;

namespace WebApi.Common
{
    public class EWSUtil
    {

        #region 获取ExchangeService对象
        /// <summary>
        /// 获取ExchangeService对象
        /// </summary>
        /// <param name="user">qf@wang520.partner.onmschina.cn</param>
        /// <param name="passwd">dory@1234</param>
        /// <param name="outlookServer">https://partner.outlook.cn/EWS/Exchange.asmx</param>
        /// <param name="version">ExchangeVersion.Exchange2013</param>//Exchange2010_SP1
        /// <returns></returns>
        public static  ExchangeService GetExchangeService(string user, string passwd, string outlookServer, ExchangeVersion version)
        {
            var webCredentials = new WebCredentials(user, passwd);
            var uri = new Uri(outlookServer);
            var service = new ExchangeService(version)
            {
                Credentials = webCredentials,
                Url = uri
            };
            return service;
        }
        #endregion

        /// <summary>
        /// 测试是否联通
        /// </summary>
        /// <param name="url"></param>
        /// <param name="user"></param>
        /// <param name="password"></param>
        /// <param name="version"></param>
        /// <param name="roomMail"></param>
        /// <returns></returns>
        /// ExchangeService service = EWSUtil.GetExchangeService("qf@wang520.partner.onmschina.cn", "dory@1234", "https://partner.outlook.cn/EWS/Exchange.asmx", ExchangeVersion.Exchange2013);
        public static async System.Threading.Tasks.Task<bool> TestEWSConnection(String user, String password, String url, ExchangeVersion version, String roomMail)
        {
            ExchangeService service = GetExchangeService(user, password, url, version);
            try
            {
                Mailbox mailBox = new Mailbox(roomMail);
                FolderId folderId = new FolderId(WellKnownFolderName.Calendar, mailBox);

                CalendarFolder cf = await CalendarFolder.Bind(service, folderId, new PropertySet());
                if (!string.IsNullOrEmpty(cf.Id.ToString()))
                {
                    return true;
                }
                else
                    return false;
            }
            catch (Exception e)
            {
                Log4Helper.Error("", "测试联通失败！", e);
                return false;
            }
        }

        #region 根据会议室的Email，获取会议
        /// <summary>
        /// 根据会议室的Email，获取会议
        /// </summary>
        /// <param name="service"></param>
        /// <param name="meetingEmail">会议室email地址</param>
        /// <param name="startDate">会议获取的开始时间</param>
        /// <param name="endDate">会议获取的结束时间</param>
        /// <param name="meetingCount">获取的会议数量</param>
        /// <returns></returns>
        //static async System.Threading.Tasks.Task GetMeetingByFoldId(ExchangeService service, string meetingEmail, DateTime startDate, DateTime endDate, int meetingCount)
        //{
        //    var folderId = new FolderId(WellKnownFolderName.Calendar, new Mailbox(meetingEmail));
        //    // Initialize the calendar folder object with only the folder ID. 
        //    CalendarFolder calendar = await CalendarFolder.Bind(service, folderId, new PropertySet());
        //    // Set the start and end time and number of appointments to retrieve.
        //    CalendarView cView = new CalendarView(startDate, endDate, meetingCount);
        //    // Limit the properties returned to the appointment's subject, start time, and end time.
        //    cView.PropertySet = new PropertySet(AppointmentSchema.Subject, AppointmentSchema.Start, AppointmentSchema.End);
        //    // Retrieve a collection of appointments by using the calendar view.
        //    FindItemsResults<Appointment> appointments = await calendar.FindAppointments(cView);
        //    var ps = new PropertySet(BasePropertySet.FirstClassProperties,
        //           AppointmentSchema.ConflictingMeetings,
        //           AppointmentSchema.ConflictingMeetingCount,
        //           AppointmentSchema.AppointmentType,
        //           //AppointmentSchema.StoreEntryId,
        //           AppointmentSchema.Recurrence,
        //           AppointmentSchema.ConferenceType,
        //           AppointmentSchema.TextBody,
        //           AppointmentSchema.Body
        //           //AppointmentSchema.EnhancedLocation,
        //           //AppointmentSchema.EntityExtractionResult
        //           );
        //    foreach (Appointment a in appointments)
        //    {
        //        await a.Load(ps);
        //        string textBody = GetHtmlText(a.Body);
        //        List<Attachment> aList = a.Attachments.ToList();
        //        foreach (var item in aList)
        //        {
        //            await item.Load();
        //            string conLocation = item.ContentLocation;
        //            //byte[] myByte = item.con;
        //            //string msg = "okffffffffffffffff";
        //            //byte[] myByte = System.Text.Encoding.UTF8.GetBytes(msg);
        //            //using (FileStream fsWrite = new FileStream(@"D:\"+item.Name, FileMode.Append))
        //            //{
        //            //    fsWrite.Write(myByte, 0, myByte.Length);
        //            //};
        //        }

        //        Console.WriteLine("MeetingId: " + a.Id);
        //        //Console.WriteLine("ConversationId: " + a.ConversationId);
        //        Console.WriteLine("MeetingId: " + a.Location);
        //        Console.WriteLine("Subject: " + a.Subject?.ToString() + " ");
        //        Console.WriteLine("Start: " + a.Start.ToString() + " ");
        //        Console.WriteLine("End: " + a.End.ToString());
        //        Console.WriteLine("DateTimeCreated: " + a.DateTimeCreated.ToString());
        //        Console.WriteLine("DateTimeSent: " + a.DateTimeSent.ToString());
        //        Console.WriteLine("DateTimeReceived: " + a.DateTimeReceived.ToString());
        //        Console.WriteLine("ConflictingMeetingCount: " + a.ConflictingMeetingCount.ToString());
        //        //AttachmentCollection atts = a.Attachments;

        //        Console.WriteLine();
        //    }
        //}
        #endregion

        #region 获取与会人员的会议
        static async System.Threading.Tasks.Task GetAttendeeMeeting(ExchangeService service, string meetingmMail)
        {
            List<AttendeeInfo> attendees = new List<AttendeeInfo>();
            attendees.Add(new AttendeeInfo(meetingmMail, MeetingAttendeeType.Organizer, true));
            GetUserAvailabilityResults results = await service.GetUserAvailability(attendees, new TimeWindow(DateTime.Now, DateTime.Now.AddDays(30)), AvailabilityData.FreeBusy);
            List<Dictionary<String, Object>> list = new List<Dictionary<String, Object>>();
            foreach (AttendeeAvailability availability in results.AttendeesAvailability)
            {
                foreach (CalendarEvent calEvent in availability.CalendarEvents)
                {
                    Dictionary<String, Object> map = new Dictionary<String, Object>();
                    // 开始时间和结束时间
                    map.Add("start", calEvent.StartTime);
                    map.Add("end", calEvent.EndTime);
                    CalendarEventDetails details = calEvent.Details;
                    if (details != null)
                    {
                        // subject中包含发件人和主题
                        String subject = details.Subject;
                        if (!string.IsNullOrEmpty(subject))
                        {
                            // 按空格区分发件人和主题
                            String[] strings = subject.Split(" ");
                            map.Add("booker", strings[0]);
                            map.Add("meetingName", strings[1]);
                        }
                    }
                    list.Add(map);
                }
            }
        }

        #endregion

        #region 创建周期性会议 
        /// <summary>
        /// 根据会议个数，开始时间与结束时间，周期会议模式 生成周期会议
        /// </summary>
        /// <param name="service"></param>
        /// <returns></returns>
        public static async System.Threading.Tasks.Task<ItemId> CreateARecurringMeetingAsync(ExchangeService service)
        {
            Appointment recurrMeeting = new Appointment(service);
            // Set the properties you need to create a meeting.
            recurrMeeting.Subject = "dayly Update Meeting";//weekly
            recurrMeeting.Body = "Come hear about how the project is coming along!";
            //DateTime dt = DateTime.Now.AddDays(2);
            //recurrMeeting.Start = new DateTime(dt.Year, dt.Month, dt.Day, 22, 00, 0);
            //recurrMeeting.End = new DateTime(dt.Year, dt.Month, DateTime.Now.AddDays(4).Day, 22, 30, 0);

            recurrMeeting.Start = DateTime.Now.AddDays(1).AddHours(1);
            //recurrMeeting.End = DateTime.Now.AddDays(7).AddHours(1);
            recurrMeeting.End = recurrMeeting.Start.AddHours(2);

            recurrMeeting.Location = "meeting";
            recurrMeeting.RequiredAttendees.Add("meeting@wang520.partner.onmschina.cn");
            recurrMeeting.RequiredAttendees.Add("bayeyang@uplussoft.com");
            recurrMeeting.OptionalAttendees.Add("bayeyang@foxmail.com");
            recurrMeeting.ReminderMinutesBeforeStart = 30;

            #region 每天
            //recurrMeeting.Recurrence = new Recurrence.DailyPattern(recurrMeeting.Start, 1);
            #endregion

            #region 周模式
            //DayOfTheWeek[] dow = new DayOfTheWeek[] { (DayOfTheWeek)recurrMeeting.Start.DayOfWeek };
            //The following are the recurrence-specific properties for the meeting.
            //recurrMeeting.Recurrence = new Recurrence.WeeklyPattern(recurrMeeting.Start.Date, 1, dow);
            #endregion

            #region 月模式
            recurrMeeting.Recurrence = new Recurrence.MonthlyPattern(recurrMeeting.Start, 1, 1);//每个月第一天
            #endregion

            recurrMeeting.Recurrence.StartDate = recurrMeeting.Start.Date;
            //recurrMeeting.Recurrence.EndDate = recurrMeeting.Start.AddDays(3);//获取或设置重复结束日期。设置EndDate会重置NumberOfOccurrences。
            recurrMeeting.Recurrence.NumberOfOccurrences = 3;
            // This method results in in a CreateItem call to EWS.
            await recurrMeeting.Save(SendInvitationsMode.SendToAllAndSaveCopy);
            // Retrieve the meeting subject and the properties that are set on a recurring master when a recurring series is created.
            recurrMeeting = await Appointment.Bind(service, recurrMeeting.Id, new PropertySet(AppointmentSchema.Subject,
                                                                                        AppointmentSchema.AppointmentType,
                                                                                        AppointmentSchema.Recurrence,
                                                                                        AppointmentSchema.FirstOccurrence,
                                                                                        AppointmentSchema.LastOccurrence,
                                                                                        AppointmentSchema.ModifiedOccurrences,
                                                                                        AppointmentSchema.DeletedOccurrences));
            // Print out the recurring master properties.
            Console.WriteLine("\nAppointment created: " + recurrMeeting.Subject);
            Console.WriteLine("Appointment Type: {0}\n", recurrMeeting.AppointmentType);
            Console.WriteLine("These property values are always null unless the item is a recurring master:\n");
            Console.WriteLine("\tRecurrence pattern: {0}", recurrMeeting.Recurrence.ToString());
            Console.WriteLine("\tRecurring series start Date: {0}", recurrMeeting.Recurrence.StartDate.ToString());
            Console.WriteLine("\tRecurring series end Date: {0}", recurrMeeting.Recurrence.EndDate == null ? "Null" : recurrMeeting.Recurrence.EndDate.ToString());
            Console.WriteLine("\tHas end: {0}", recurrMeeting.Recurrence.HasEnd.ToString());
            Console.WriteLine("\tNumber of occurrances: {0}", recurrMeeting.Recurrence.NumberOfOccurrences);
            Console.WriteLine("\tLast 24 characters of the first occurrence's item ID:\t {0}",
                            recurrMeeting.FirstOccurrence.ItemId.ToString().Substring(144));
            Console.WriteLine("\tLast 24 characters of the last occurrence's item ID:\t {0}",
                            recurrMeeting.LastOccurrence.ItemId.ToString().Substring(144));
            Console.WriteLine("\tModified Occurrences: {0}",
                            (recurrMeeting.ModifiedOccurrences == null ? "Null" : recurrMeeting.ModifiedOccurrences.Count.ToString()));
            Console.WriteLine("\tDeleted Occurrences: {0}",
                            recurrMeeting.DeletedOccurrences == null ? "Null" : recurrMeeting.ModifiedOccurrences.Count.ToString());
            // Return the ID of the recurring master.
            return recurrMeeting.Id;
        }
        #endregion


        #region 删除日历
        static async System.Threading.Tasks.Task DeleteAppointment(ExchangeService service, string appointmentId)
        {
            try
            {
                //new PropertySet()
                var ps = new PropertySet(BasePropertySet.FirstClassProperties,
                       AppointmentSchema.ConflictingMeetings,
                       AppointmentSchema.ConflictingMeetingCount,
                       AppointmentSchema.AppointmentType,
                       //AppointmentSchema.StoreEntryId,
                       AppointmentSchema.Recurrence,
                       AppointmentSchema.ConferenceType
                       //AppointmentSchema.EnhancedLocation,
                       //AppointmentSchema.EntityExtractionResult
                       );

                // Instantiate an appointment object by binding to it by using the ItemId.
                // As a best practice, limit the properties returned to only the ones you need.
                // Appointment appointment = await Appointment.Bind(service, appointmentId, new PropertySet());

                Appointment appointment = await Appointment.Bind(service, appointmentId, ps);
                // Delete the appointment. Note that the item ID will change when the item is moved to the Deleted Items folder.
                await appointment.Delete(DeleteMode.MoveToDeletedItems);
                // Verify that the appointment has been deleted by looking for a matching subject in the Deleted Items folder's first entry.
                ItemView itemView = new ItemView(1);
                itemView.Traversal = ItemTraversal.Shallow;
                // Just retrieve the properties you need.
                itemView.PropertySet = new PropertySet(ItemSchema.Id, ItemSchema.ParentFolderId, ItemSchema.Subject);
                // Note that the FindItems method results in a call to EWS.
                FindItemsResults<Item> deletedItems = await service.FindItems(WellKnownFolderName.DeletedItems, itemView);
                Item deletedItem = deletedItems.First();
                Folder parentFolder = await Folder.Bind(service, deletedItem.ParentFolderId, new PropertySet(FolderSchema.DisplayName));
                Console.WriteLine("The appointment " + "\"" + deletedItem.Subject + "\"" + " is now in the " + parentFolder.DisplayName + " folder.");

            }
            catch (Exception ex)
            {
                Log4Helper.Error("", "删除日历失败！", ex);
            }

        }
        #endregion

        #region 更新日历会议
        static async System.Threading.Tasks.Task updateAppointment(ExchangeService service, string appointmentId)
        {
            try
            {

                // Instantiate an appointment object by binding to it by using the ItemId.
                // As a best practice, limit the properties returned to only the ones you need.
                Appointment appointment = await Appointment.Bind(service, appointmentId, new PropertySet(AppointmentSchema.Subject, AppointmentSchema.Start, AppointmentSchema.End));
                await appointment.Load();



                string oldSubject = appointment.Subject;
                // Update properties on the appointment with a new subject, start time, and end time.
                appointment.Subject = appointment.Subject + " moved one hour later and to the day after " + appointment.Start.DayOfWeek + "!";
                //appointment.Start.AddHours(25);
                //appointment.End.AddHours(25);
                // Unless explicitly specified, the default is to use SendToAllAndSaveCopy.
                // This can convert an appointment into a meeting. To avoid this,
                // explicitly set SendToNone on non-meetings.
                SendInvitationsOrCancellationsMode mode = appointment.IsMeeting ?
                    SendInvitationsOrCancellationsMode.SendToAllAndSaveCopy : SendInvitationsOrCancellationsMode.SendToNone;
                // Send the update request to the Exchange server.
                await appointment.Update(ConflictResolutionMode.AlwaysOverwrite, mode);
                // Verify the update.
                Console.WriteLine("Subject for the appointment was \"" + oldSubject + "\". The new subject is \"" + appointment.Subject + "\"");

            }
            catch (Exception ex)
            {
                Log4Helper.Error("", "更新日历会议失败！", ex);
            }

        }
        #endregion


        /// <summary>
        /// 获取html中的纯文本
        /// </summary>
        /// <param name="html">会议内容</param>
        /// <returns>纯文本（即会议内容）</returns>
        public static string GetHtmlText(string html)
        {
            html = System.Text.RegularExpressions.Regex.Replace(html, @"<\/*[^<>]*>", "", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            html = html.Replace("\r\n", "").Replace("\r", "").Replace("&nbsp;", "").Replace(" ", "");
            return html;
        }

        
    }
}
